#pragma once
/*
模块说明：该模块向外提供接口给客户端使用，功能是发送基于json串的Rpc请求
里面包含一个requestor对象来管理发送出去的Rpc请求和提供处理Rpc回应的方法
用户传入把请求方法string对象和参数用json串传入到该模块中，然后经过协议层转添加报头为一个Message对象再交给
requestor对象管理并且发送给服务端
*/
#include "requestor.hpp"

class Rpc_Caller
{
public:
    using RpcCallPtr=std::shared_ptr<Rpc_Caller>;
    using RpcJsonResCallBack = std::function<void(const Json::Value &)>;
    Rpc_Caller(std::shared_ptr <Client::Resquestor>& Requestor):_Requestor(Requestor)
    {

    }

    // 基于发送线程同步等待请求结果的发送方式，在发送完请求和阻塞等待返回结果
    bool call(const Abstract::BaseConnection::ConPtr &ConPtr, const std::string &method,
              const Json::Value &params, Json::Value &result)
    {
        // 1 组指 请求
        auto RpcRequst = Message::BuildMessage::build<Message::RpcRequest>();
        RpcRequst->SetUuid(UUID::uuid());
        RpcRequst->SetMtype(Rs_RqType::RPC_Req);
        RpcRequst->SetMethod(method);
        RpcRequst->SetParams(params);
        Abstract::BaseMessage::MesaPtr Base_Res; // 构建一个空的基类指针去接收协议层传过来的RpcResponce的基类指针

        //ELOG("进入发送Rpc请求模块");
        // 2 发送请求并且阻塞等待服务端回应,把从协议层获取的基类message智能指针对象赋值给Base_Res
        bool ret = _Requestor->Send(ConPtr, std::dynamic_pointer_cast<Abstract::BaseMessage>(RpcRequst), Base_Res);
        if (ret == false)
        {
           // ELOG("发送请求失败");
            return false;
        }

        // 3 把获取的基类指针转回子类Rpcmessage指针指针
        auto Rpc_ResPtr = std::dynamic_pointer_cast<Message::RpcReponceJson>(Base_Res);
        if (Rpc_ResPtr.get() == nullptr)
        {
            //ELOG("Rpc响应的基类指针向下转化失败");
            return false;
        }
        if (Rpc_ResPtr->Getcode() != ResCode::ResCode_Ok)
        {
            //ELOG("Rpc回应结果出错:%s", GetResCodeStr(Rpc_ResPtr->Getcode()).c_str());
            return false;
        }
        result = Rpc_ResPtr->GetResult(); // 获取存储计算的结果的values对象
        return true;
    }
    // 发送线程基于future对象的模式异步获取Rpc回应,
    bool call(const Abstract::BaseConnection::ConPtr &ConPtr, const std::string &method,
              const Json::Value &params, std::future<Json::Value> &result, std::string &uuid)
    {

        // 1 组指请求对象
        auto RpcRequst = Message::BuildMessage::build<Message::RpcRequest>();
        RpcRequst->SetUuid(UUID::uuid());
        RpcRequst->SetMtype(Rs_RqType::RPC_Req);
        RpcRequst->SetMethod(method);
        RpcRequst->SetParams(params);
        // 局部的promise被销毁导致发送的线程通过future对象获取Rpc结果时出错
        std::shared_ptr<std::promise<Json::Value>> Pro_ptr = std::make_shared<std::promise<Json::Value>>();
        result = Pro_ptr->get_future();
        // 2 发送请求并且阻塞等待服务端回应,把从协议层获取的基类message智能指针对象赋值给Base_Res
        bool ret = _Requestor->Send(ConPtr, std::dynamic_pointer_cast<Abstract::BaseMessage>(RpcRequst), uuid,
                                   [this, Pro_ptr](const Abstract::BaseMessage::MesaPtr &Mptr) -> void
                                   {
                                       CallBack(Mptr, Pro_ptr); // 值捕捉promise对象到 _Requestor内部去获取Rpc响应的结果
                                   });
        if (ret == false)
        {
            ELOG("基于回调函数获取回应的异步发送请求失败");
            return false;
        }
        return true;
    }

    // 基于用户传入的回调函数异步直接处理Rpc回应的计算结果
    bool call(const Abstract::BaseConnection::ConPtr &ConPtr, const std::string &method,
              const Json::Value &params, std::string &uuid, const RpcJsonResCallBack &Rb)
    {
        // 1 组指请求对象
        auto RpcRequst = Message::BuildMessage::build<Message::RpcRequest>();
        RpcRequst->SetUuid(UUID::uuid());
        RpcRequst->SetMtype(Rs_RqType::RPC_Req);
        RpcRequst->SetMethod(method);
        RpcRequst->SetParams(params);
        bool ret = _Requestor->Send(ConPtr, std::dynamic_pointer_cast<Abstract::BaseMessage>(RpcRequst), uuid,
                                   [this, Rb](const Abstract::BaseMessage::MesaPtr &Mptr) -> void
                                   {
                                       CallBack1(Rb,Mptr); // 值捕捉promise对象到 _Requestor内部去获取Rpc响应的结果
                                   });
        if (ret == false)
        {
            ELOG("基于回调函数获取回应的异步发送请求失败");
            return false;
        }
        return true;
    }

    // 提供接口给基于异步请求方式的线程用于删除_Requestor中的请求描述对象
    void DelRequestDesc(const std::string &uuid)
    {
        _Requestor->DelDescResq(uuid);
    }

private:
    // 使用回调函数把promise对象和requestor模块对应的请求描述对象绑定起来，外部的发送线程就可以通过future对象去获取Rpc回应
    void CallBack1(const RpcJsonResCallBack &Rb, const Abstract::BaseMessage::MesaPtr &Mptr)
    {
        // 3 把获取的基类指针转回子类Rpcmessage指针指针
        auto Rpc_ResPtr = std::dynamic_pointer_cast<Message::RpcReponceJson>(Mptr);
        if (Rpc_ResPtr.get() == nullptr)
        {
            ELOG("Rpc响应的基类指针向下转化失败");
        }
        if (Rpc_ResPtr->Getcode() != ResCode::ResCode_Ok)
        {
            ELOG("Rpc回应结果出错:%s", GetResCodeStr(Rpc_ResPtr->Getcode()).c_str());
        }
        Rb(Rpc_ResPtr->GetResult());//基于用户的回调直接处理RPc回应
        DelRequestDesc(Rpc_ResPtr->GetUuid());//回调处理完成后删除该Rpc请求的描述对象
    }

    // 使用回调函数把promise对象和requestor模块对应的请求描述对象绑定起来，外部的发送线程就可以通过future对象去获取Rpc回应
    void CallBack(const Abstract::BaseMessage::MesaPtr &Mptr, std::shared_ptr<std::promise<Json::Value>> Pro_ptr)
    {
        // 3 把获取的基类指针转回子类Rpcmessage指针指针
        auto Rpc_ResPtr = std::dynamic_pointer_cast<Message::RpcReponceJson>(Mptr);
        if (Rpc_ResPtr.get() == nullptr)
        {
            ELOG("Rpc响应的基类指针向下转化失败");
        }
        if (Rpc_ResPtr->Getcode() != ResCode::ResCode_Ok)
        {
            ELOG("Rpc回应结果出错:%s", GetResCodeStr(Rpc_ResPtr->Getcode()).c_str());
        }
        Pro_ptr->set_value(Rpc_ResPtr->GetResult()); // 获取存储计算的结果的values对象
    }

private:
    std::shared_ptr <Client::Resquestor> _Requestor; // 负责管理发送出去的请求和发送请求和处理回应
};